package com.bi.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bi.entity.DataComponent;
import com.bi.entity.DataComponentField;
import com.bi.entity.WideTable;
import com.bi.mapper.DataComponentMapper;
import com.bi.service.DataComponentFieldService;
import com.bi.service.DataComponentService;
import com.bi.service.WideTableService;
import com.bi.vo.WideTableVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 数据组件服务实现类
 * 
 * @author BI Platform Team
 * @since 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DataComponentServiceImpl extends ServiceImpl<DataComponentMapper, DataComponent> implements DataComponentService {

    private final DataComponentFieldService dataComponentFieldService;
    private final WideTableService wideTableService;
    private final RedisTemplate<String, Object> redisTemplate;

    private static final String COMPONENT_CACHE_KEY = "data_component:";
    private static final String COMPONENT_DATA_CACHE_KEY = "component_data:";

    @Override
    public IPage<DataComponent> getComponentPage(long current, long size, Map<String, Object> params) {
        Page<DataComponent> page = new Page<>(current, size);
        return baseMapper.selectComponentPage(page, params);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createComponent(DataComponent component, List<DataComponentField> fields) {
        try {
            // 设置创建时间
            component.setCreateTime(LocalDateTime.now());
            component.setUpdateTime(LocalDateTime.now());
            
            // 保存组件基本信息
            boolean saveResult = save(component);
            if (!saveResult) {
                return false;
            }

            // 保存字段配置
            if (fields != null && !fields.isEmpty()) {
                boolean saveFieldResult = dataComponentFieldService.saveFields(component.getId(), fields);
                if (!saveFieldResult) {
                    throw new RuntimeException("保存字段配置失败");
                }
            }

            // 清除相关缓存
            clearComponentCache(component.getId());

            log.info("创建数据组件成功: id={}, name={}", component.getId(), component.getName());
            return true;

        } catch (Exception e) {
            log.error("创建数据组件失败: name={}, error={}", component.getName(), e.getMessage(), e);
            throw new RuntimeException("创建数据组件失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateComponent(DataComponent component, List<DataComponentField> fields) {
        try {
            // 设置更新时间
            component.setUpdateTime(LocalDateTime.now());
            
            // 更新组件基本信息
            boolean updateResult = updateById(component);
            if (!updateResult) {
                return false;
            }

            // 更新字段配置
            if (fields != null) {
                // 先删除原有字段配置
                dataComponentFieldService.deleteFieldsByComponentId(component.getId());
                
                // 保存新的字段配置
                if (!fields.isEmpty()) {
                    boolean saveFieldResult = dataComponentFieldService.saveFields(component.getId(), fields);
                    if (!saveFieldResult) {
                        throw new RuntimeException("更新字段配置失败");
                    }
                }
            }

            // 清除相关缓存
            clearComponentCache(component.getId());

            log.info("更新数据组件成功: id={}, name={}", component.getId(), component.getName());
            return true;

        } catch (Exception e) {
            log.error("更新数据组件失败: id={}, error={}", component.getId(), e.getMessage(), e);
            throw new RuntimeException("更新数据组件失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteComponent(Long id) {
        try {
            // 删除字段配置
            dataComponentFieldService.deleteFieldsByComponentId(id);
            
            // 删除组件
            boolean deleteResult = removeById(id);
            
            // 清除缓存
            clearComponentCache(id);
            
            log.info("删除数据组件成功: id={}", id);
            return deleteResult;

        } catch (Exception e) {
            log.error("删除数据组件失败: id={}, error={}", id, e.getMessage(), e);
            throw new RuntimeException("删除数据组件失败: " + e.getMessage());
        }
    }

    @Override
    public List<DataComponent> getComponentsByType(String type) {
        return baseMapper.selectByType(type);
    }

    @Override
    public Map<String, Object> getStatistics() {
        return baseMapper.selectStatistics();
    }

    @Override
    public Map<String, Object> testDataSource(DataComponent component) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            switch (component.getDataSourceType()) {
                case WIDE_TABLE:
                    result = testWideTableDataSource(component);
                    break;
                case ELASTICSEARCH:
                    result = testElasticsearchDataSource(component);
                    break;
                case API:
                    result = testApiDataSource(component);
                    break;
                case DATABASE:
                    result = testDatabaseDataSource(component);
                    break;
                default:
                    result.put("success", false);
                    result.put("message", "不支持的数据源类型");
            }
        } catch (Exception e) {
            log.error("测试数据源失败: type={}, error={}", component.getDataSourceType(), e.getMessage());
            result.put("success", false);
            result.put("message", "测试失败: " + e.getMessage());
        }
        
        return result;
    }

    @Override
    public Map<String, Object> executeQuery(Long componentId, Map<String, Object> params) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 检查缓存
            String cacheKey = COMPONENT_DATA_CACHE_KEY + componentId + ":" + params.hashCode();
            Object cachedObject = redisTemplate.opsForValue().get(cacheKey);
            if (cachedObject instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<String, Object> cachedData = (Map<String, Object>) cachedObject;
                return cachedData;
            }

            // 获取组件配置
            DataComponent component = getById(componentId);
            if (component == null) {
                result.put("success", false);
                result.put("message", "组件不存在");
                return result;
            }

            // 获取字段配置
            List<DataComponentField> fields = dataComponentFieldService.getFieldsByComponentId(componentId);

            // 执行查询
            switch (component.getDataSourceType()) {
                case WIDE_TABLE:
                    result = executeWideTableQuery(component, fields, params);
                    break;
                case ELASTICSEARCH:
                    result = executeElasticsearchQuery(component, fields, params);
                    break;
                case API:
                    result = executeApiQuery(component, fields, params);
                    break;
                case DATABASE:
                    result = executeDatabaseQuery(component, fields, params);
                    break;
                default:
                    result.put("success", false);
                    result.put("message", "不支持的数据源类型");
            }

            // 缓存结果
            if ((Boolean) result.getOrDefault("success", false)) {
                int cacheTime = component.getRefreshInterval() != null ? component.getRefreshInterval() : 30;
                redisTemplate.opsForValue().set(cacheKey, result, cacheTime, TimeUnit.MINUTES);
            }

        } catch (Exception e) {
            log.error("执行组件查询失败: componentId={}, error={}", componentId, e.getMessage(), e);
            result.put("success", false);
            result.put("message", "查询失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    public Map<String, Object> previewData(DataComponent component, List<DataComponentField> fields, Map<String, Object> params) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 限制预览数据量
            params.put("pageSize", 10);
            params.put("current", 1);

            switch (component.getDataSourceType()) {
                case WIDE_TABLE:
                    result = executeWideTableQuery(component, fields, params);
                    break;
                case ELASTICSEARCH:
                    result = executeElasticsearchQuery(component, fields, params);
                    break;
                case API:
                    result = executeApiQuery(component, fields, params);
                    break;
                case DATABASE:
                    result = executeDatabaseQuery(component, fields, params);
                    break;
                default:
                    result.put("success", false);
                    result.put("message", "不支持的数据源类型");
            }

        } catch (Exception e) {
            log.error("预览组件数据失败: error={}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "预览失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    public boolean refreshCache(Long componentId) {
        try {
            clearComponentCache(componentId);
            log.info("刷新组件缓存成功: componentId={}", componentId);
            return true;
        } catch (Exception e) {
            log.error("刷新组件缓存失败: componentId={}, error={}", componentId, e.getMessage());
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DataComponent copyComponent(Long componentId, String newName) {
        try {
            // 获取原组件
            DataComponent sourceComponent = getById(componentId);
            if (sourceComponent == null) {
                throw new RuntimeException("源组件不存在");
            }

            // 创建新组件
            DataComponent newComponent = new DataComponent();
            newComponent.setName(newName);
            newComponent.setDisplayName(sourceComponent.getDisplayName() + "_副本");
            newComponent.setDescription(sourceComponent.getDescription());
            newComponent.setType(sourceComponent.getType());
            newComponent.setDataSourceType(sourceComponent.getDataSourceType());
            newComponent.setDataSourceConfig(sourceComponent.getDataSourceConfig());
            newComponent.setWideTableId(sourceComponent.getWideTableId());
            newComponent.setSqlQuery(sourceComponent.getSqlQuery());
            newComponent.setEsQuery(sourceComponent.getEsQuery());
            newComponent.setApiConfig(sourceComponent.getApiConfig());
            newComponent.setFieldMapping(sourceComponent.getFieldMapping());
            newComponent.setCacheConfig(sourceComponent.getCacheConfig());
            newComponent.setRefreshInterval(sourceComponent.getRefreshInterval());
            newComponent.setStatus(DataComponent.ComponentStatus.DRAFT);
            newComponent.setCreator(sourceComponent.getCreator());

            boolean saveResult = save(newComponent);
            if (!saveResult) {
                throw new RuntimeException("保存新组件失败");
            }

            // 复制字段配置
            boolean copyFieldResult = dataComponentFieldService.copyFields(componentId, newComponent.getId());
            if (!copyFieldResult) {
                throw new RuntimeException("复制字段配置失败");
            }

            log.info("复制数据组件成功: sourceId={}, newId={}, newName={}", componentId, newComponent.getId(), newName);
            return newComponent;

        } catch (Exception e) {
            log.error("复制数据组件失败: componentId={}, newName={}, error={}", componentId, newName, e.getMessage(), e);
            throw new RuntimeException("复制数据组件失败: " + e.getMessage());
        }
    }

    // 私有方法实现

    private Map<String, Object> testWideTableDataSource(DataComponent component) {
        Map<String, Object> result = new HashMap<>();
        
        if (component.getWideTableId() == null) {
            result.put("success", false);
            result.put("message", "宽表ID不能为空");
            return result;
        }

        WideTableVO wideTable = wideTableService.getWideTableById(component.getWideTableId());
        if (wideTable == null) {
            result.put("success", false);
            result.put("message", "宽表不存在");
            return result;
        }

        if (wideTable.getStatus() != WideTable.WideTableStatus.ACTIVE) {
            result.put("success", false);
            result.put("message", "宽表未激活");
            return result;
        }

        result.put("success", true);
        result.put("message", "连接成功");
        result.put("dataCount", wideTable.getDataCount());
        return result;
    }

    private Map<String, Object> testElasticsearchDataSource(DataComponent component) {
        Map<String, Object> result = new HashMap<>();
        
        if (!StringUtils.hasText(component.getEsQuery())) {
            result.put("success", false);
            result.put("message", "ES查询配置不能为空");
            return result;
        }

        // 这里应该实际测试ES连接
        result.put("success", true);
        result.put("message", "ES连接测试成功");
        return result;
    }

    private Map<String, Object> testApiDataSource(DataComponent component) {
        Map<String, Object> result = new HashMap<>();
        
        if (!StringUtils.hasText(component.getApiConfig())) {
            result.put("success", false);
            result.put("message", "API配置不能为空");
            return result;
        }

        // 这里应该实际测试API连接
        result.put("success", true);
        result.put("message", "API连接测试成功");
        return result;
    }

    private Map<String, Object> testDatabaseDataSource(DataComponent component) {
        Map<String, Object> result = new HashMap<>();
        
        if (!StringUtils.hasText(component.getSqlQuery())) {
            result.put("success", false);
            result.put("message", "SQL查询不能为空");
            return result;
        }

        // 这里应该实际测试数据库连接
        result.put("success", true);
        result.put("message", "数据库连接测试成功");
        return result;
    }

    private Map<String, Object> executeWideTableQuery(DataComponent component, List<DataComponentField> fields, Map<String, Object> params) {
        // 简化实现，实际应该根据字段配置构建查询
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("data", List.of());
        result.put("total", 0);
        return result;
    }

    private Map<String, Object> executeElasticsearchQuery(DataComponent component, List<DataComponentField> fields, Map<String, Object> params) {
        // 简化实现，实际应该执行ES查询
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("data", List.of());
        result.put("total", 0);
        return result;
    }

    private Map<String, Object> executeApiQuery(DataComponent component, List<DataComponentField> fields, Map<String, Object> params) {
        // 简化实现，实际应该调用API
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("data", List.of());
        result.put("total", 0);
        return result;
    }

    private Map<String, Object> executeDatabaseQuery(DataComponent component, List<DataComponentField> fields, Map<String, Object> params) {
        // 简化实现，实际应该执行SQL查询
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("data", List.of());
        result.put("total", 0);
        return result;
    }

    private void clearComponentCache(Long componentId) {
        // 清除组件缓存
        redisTemplate.delete(COMPONENT_CACHE_KEY + componentId);
        
        // 清除数据缓存（模糊匹配）
        String pattern = COMPONENT_DATA_CACHE_KEY + componentId + ":*";
        redisTemplate.delete(redisTemplate.keys(pattern));
    }
}